package com.example.demoweb.controller;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.security.NoSuchAlgorithmException;
import java.util.List;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.gridfs.GridFsTemplate;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.example.demoweb.entity.CustomFile;
import com.example.demoweb.service.ICustomFileService;
import com.example.demoweb.util.MD5Util;
import com.mongodb.gridfs.GridFSDBFile;

@CrossOrigin(origins = "*", maxAge = 3600)
@RestController
public class CustomFileController {
    @Autowired
    private ICustomFileService customFileService;
    
    @Autowired
    private GridFsTemplate gridFsTemplate;

    /*@Value("${server.address}")
    private String serverAddress;*/

    @Value("${server.port}")
    private String serverPort;

    @RequestMapping("/file")
    public ModelAndView index(Model model) {
        // 展示最新二十条数据
        List<CustomFile> customFiles = customFileService.listFilesByPage(0,20); 
        ModelAndView mv = new ModelAndView("fileTest");
        mv.addObject("files",customFiles);
        return mv;
    }

    /**
     * 分页查询文件
     * @param pageIndex
     * @param pageSize
     * @return
     */
    @GetMapping("files/{pageIndex}/{pageSize}")
    @ResponseBody
    public List<CustomFile> listFilesByPage(@PathVariable int pageIndex, @PathVariable int pageSize){
        return customFileService.listFilesByPage(pageIndex, pageSize);
    }

    /**
     * 获取文件片信息
     * @param id
     * @return
     */
    @GetMapping("files/{id}")
    @ResponseBody
    public ResponseEntity<Object> serveFile(@PathVariable String id) {

        CustomFile customFile = customFileService.getFileById(id);

        if (customFile != null) {
            return ResponseEntity
                    .ok()
                    .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; fileName=\"" + customFile.getName() + "\"")
                    .header(HttpHeaders.CONTENT_TYPE, "application/octet-stream" )
                    .header(HttpHeaders.CONTENT_LENGTH, customFile.getSize()+"")
                    .header("Connection",  "close") 
                    .body( customFile.getContent());
        } else {
            return ResponseEntity.status(HttpStatus.NOT_FOUND).body("File was not fount");
        }

    }

    /**
     * 在线显示文件
     * @param id
     * @return
     */
    @GetMapping("/view/{id}")
    @ResponseBody
    public ResponseEntity<Object> serveFileOnline(@PathVariable String id) {

        CustomFile customFile = customFileService.getFileById(id);

        if (customFile != null) {
            return ResponseEntity
                    .ok()
                    .header(HttpHeaders.CONTENT_DISPOSITION, "fileName=\"" + customFile.getName() + "\"")
                    .header(HttpHeaders.CONTENT_TYPE, customFile.getContentType() )
                    .header(HttpHeaders.CONTENT_LENGTH, customFile.getSize()+"")
                    .header("Connection",  "close") 
                    .body( customFile.getContent());
        } else {
            return ResponseEntity.status(HttpStatus.NOT_FOUND).body("File was not fount");
        }

    }

    /**
     * 上传
     * @param file
     * @param redirectAttributes
     * @return
     */
    @PostMapping("/upload")
    public String handleFileUpload(@RequestParam("file") MultipartFile file,
                                   RedirectAttributes redirectAttributes) throws NoSuchAlgorithmException {

        try {
            CustomFile f = new CustomFile(file.getOriginalFilename(),  file.getContentType(), file.getSize(), file.getBytes());
            f.setMd5( MD5Util.getMD5(file.getInputStream()) );
            customFileService.saveFile(f);
        } catch (IOException ex) {
            ex.printStackTrace();
            redirectAttributes.addFlashAttribute("message",
                    "Your " + file.getOriginalFilename() + " is wrong!");
            return "redirect:/";
        }

        redirectAttributes.addFlashAttribute("message",
                "You successfully uploaded " + file.getOriginalFilename() + "!");

        return "redirect:/";
    }

    /**
     * 上传接口
     * @param file
     * @return
     */
    @PostMapping("/uploadAndReturn")
    @ResponseBody
    public ResponseEntity<String> handleFileUpload(@RequestParam("file") MultipartFile file) throws NoSuchAlgorithmException {
        CustomFile returnFile = null;
        try {
            CustomFile f = new CustomFile(file.getOriginalFilename(),  file.getContentType(), file.getSize(),file.getBytes());
            f.setMd5( MD5Util.getMD5(file.getInputStream()) );
            returnFile = customFileService.saveFile(f);
            //String path = "//"+ serverAddress + ":" + serverPort + "/view/"+returnFile.getId();
            String path = "//"+ serverPort + "/view/"+returnFile.getId();
            return ResponseEntity.status(HttpStatus.OK).body(path);

        } catch (IOException ex) {
            ex.printStackTrace();
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(ex.getMessage());
        }

    }

    /**
     * 删除文件
     * @param id
     * @return
     */
    @DeleteMapping("/{id}")
    @ResponseBody
    public ResponseEntity<String> deleteFile(@PathVariable String id) {

        try {
            customFileService.removeFile(id);
            return ResponseEntity.status(HttpStatus.OK).body("DELETE Success!");
        } catch (Exception e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage());
        }
    }
    /**
     * FridFs 存文件
     */
    @PostMapping("/uploadGridFs")
    public void storeFileInGridFs(@RequestParam("file") MultipartFile file) {
        try {
        	gridFsTemplate.store(file.getInputStream(), file.getOriginalFilename(), file.getContentType());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * FridFs 下载文件
     * @throws IOException
     */
    @GetMapping("/findFilesInGridFs/{fileName}")
    public void findFilesInGridFs(HttpServletResponse response,@PathVariable("fileName") String fileName) throws IOException {
    	Query query = new Query();
    	query.addCriteria(Criteria.where("filename").is("123.jpg"));
        List<GridFSDBFile> result = gridFsTemplate.find(query);
        GridFSDBFile resultFile = result.get(0);
        
        if (!resultFile.equals(null)) {
			try {
				InputStream in = resultFile.getInputStream();
				
				response.addHeader("Content-Disposition", "attachment;filename="+new String((resultFile.getFilename()).getBytes("GB2312"),"iso8859-1"));
				response.setContentType("application/octet-stream");	
					 try {
						IOUtils.copy(in,response.getOutputStream());    
					} catch (IOException e) {
						e.printStackTrace();
					}finally{
						in.close();
					}
			} catch (Exception e1) {
				e1.printStackTrace();
			}
		}
    }
}
